package com.example.mymessagequeue.mqserver.service;

import com.example.mymessagequeue.common.*;
import com.example.mymessagequeue.mqserver.VirtualHost;
import com.example.mymessagequeue.mqserver.core.Binding;
import com.example.mymessagequeue.mqserver.core.Exchange;
import com.example.mymessagequeue.mqserver.core.Message;
import com.example.mymessagequeue.mqserver.core.MsgQueue;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class EagleService {

    /**
     * 创建交换机
     * @param arguments 创建交换机所需的参数
     * @param virtualHostName 虚拟主机名
     * @return
     */
    public boolean exchangeDeclare(ExchangeDeclareArguments arguments, String virtualHostName) {
        VirtualHost virtualHost = GlobalVariable.brokerServer.getVirtualHost(virtualHostName);
        if (virtualHost == null) {
            return false;
        }
        return  virtualHost.exchangeDeclare(
                arguments.getExchangeName(),
                arguments.getExchangeType(),
                arguments.isDurable(),
                arguments.isAutoDelete(),
                arguments.getArguments()
        );
    }

    /**
     * 删除交换机
     * @param arguments 删除交换机所需的参数
     * @param virtualHostName 虚拟主机名
     */
    public boolean exchangeDelete(ExchangeDeleteArguments arguments, String virtualHostName) {
        VirtualHost virtualHost = GlobalVariable.brokerServer.getVirtualHost(virtualHostName);
        if (virtualHost == null) {
            return false;
        }
        return virtualHost.exchangeDelete(arguments.getExchangeName());
    }

    /**
     * 创建交换机
     * @param arguments
     * @param virtualHostName
     * @return
     */
    public boolean queueDeclare(QueueDeclareArguments arguments, String virtualHostName) {
        VirtualHost virtualHost = GlobalVariable.brokerServer.getVirtualHost(virtualHostName);
        if (virtualHost == null) {
            return false;
        }
        return virtualHost.queueDeclare(
                arguments.getQueueName(),
                arguments.isDurable(),
                arguments.isExclusive(),
                arguments.isAutoDelete(),
                arguments.getArguments()
        );
    }

    /**
     * 删除队列
     * @param arguments
     * @param virtualHostName
     * @return
     */
    public boolean queueDelete(QueueDeleteArguments arguments, String virtualHostName) {
        VirtualHost virtualHost = GlobalVariable.brokerServer.getVirtualHost(virtualHostName);
        if (virtualHost == null) {
            return false;
        }
        return virtualHost.queueDelete(arguments.getQueueName());
    }

    /**
     * 将队列与交换机进行绑定
     * @param arguments
     * @param virtualHostName
     * @return
     */
    public boolean queueBind(QueueBindArguments arguments, String virtualHostName) {
        VirtualHost virtualHost = GlobalVariable.brokerServer.getVirtualHost(virtualHostName);
        if (virtualHost == null) {
            return false;
        }
        return virtualHost.queueBind(arguments.getQueueName(), arguments.getExchangeName(), arguments.getBindingKey());
    }

    /**
     * 将队列与交换机解除绑定
     * @param arguments
     * @param virtualHostName
     * @return
     */
    public boolean queueUnbind(QueueUnbindArguments arguments, String virtualHostName) {
        VirtualHost virtualHost = GlobalVariable.brokerServer.getVirtualHost(virtualHostName);
        if (virtualHost == null) {
            return false;
        }
        return virtualHost.queueUnbind(arguments.getQueueName(), arguments.getExchangeName());
    }

    public boolean basicPublish(BasicPublishArguments arguments, String virtualHostName) {
        VirtualHost virtualHost = GlobalVariable.brokerServer.getVirtualHost(virtualHostName);
        if (virtualHost == null) {
            return false;
        }
        return virtualHost.basicPublish(
                arguments.getExchangeName(),
                arguments.getRoutingKey(),
                arguments.getBasicProperties(),
                arguments.getBody()
        );
    }

    /**
     * 查询所有的队列
     * @param virtualHostName
     * @return
     */
    public List<MsgQueue> selectAllQueues(String virtualHostName) {
        VirtualHost virtualHost = GlobalVariable.brokerServer.getVirtualHost(virtualHostName);
        if (virtualHost == null) {
            return new ArrayList<>();
        }
        return virtualHost.getMemoryDataCenter().selectAllQueues();
    }

    /**
     * 查询所有的交换机
     * @param virtualHostName 虚拟主机名
     * @return
     */
    public List<Exchange> selectAllExchanges(String virtualHostName) {
        VirtualHost virtualHost = GlobalVariable.brokerServer.getVirtualHost(virtualHostName);
        if (virtualHost == null) {
            return new ArrayList<>();
        }
        return virtualHost.getMemoryDataCenter().selectAllExchanges();
    }

    /**
     * 查询所有的绑定
     * @param virtualHostName
     * @return
     */
    public List<Binding> selectAllBindings(String virtualHostName) {
        VirtualHost virtualHost = GlobalVariable.brokerServer.getVirtualHost(virtualHostName);
        if (virtualHost == null) {
            return new ArrayList<>();
        }
        return virtualHost.getMemoryDataCenter().selectAllBindings();
    }

    /**
     * 通过队列名查找指定的队列
     * @param queueName
     * @param virtualHostName
     * @return
     */
    public MsgQueue selectQueue(String queueName, String virtualHostName) {
        VirtualHost virtualHost = GlobalVariable.brokerServer.getVirtualHost(virtualHostName);
        if (virtualHost == null) {
            return null;
        }
        // 两种查询方式:
        // 1. 完整查询, 队列名为: 虚拟主机名.队列名
        // 2. 队列名拆线呢, 队列名为: 队列名
        // 先使用完整查询

        MsgQueue queue = virtualHost.getMemoryDataCenter().getQueue(queueName);
        if (queue != null) {
            return queue;
        }
        // 拼接虚拟主机前缀查询
        return virtualHost.getMemoryDataCenter().getQueue(virtualHost.getName(queueName));
    }

    /**
     * 查找指定交换机
     * @param exchangeName 交换机名
     * @param virtualHostName 虚拟主机名
     * @return
     */
    public Exchange selectExchange(String exchangeName, String virtualHostName) {
        VirtualHost virtualHost = GlobalVariable.brokerServer.getVirtualHost(virtualHostName);
        if (virtualHost == null) {
            return null;
        }
        // 允许使用两个名称去查询：
        // 1. 允许使用 虚拟主机名.交换机名 查询
        // 2. 允许使用 交换机名 查询
        Exchange exchange = virtualHost.getMemoryDataCenter().selectExchange(exchangeName);
        if (exchange != null) {
            return exchange;
        }
        // exchange 为空, 尝试拼接名字进行查询
        return virtualHost.getMemoryDataCenter().selectExchange(virtualHost.getName(exchangeName));
    }

    /**
     * 通过交换机名和队列名查找指定的绑定对象
     * @param exchangeName
     * @param queueName
     * @param virtualHostName
     * @return
     */
    public Binding selectBinding(String exchangeName, String queueName, String virtualHostName) {
        VirtualHost virtualHost = GlobalVariable.brokerServer.getVirtualHost(virtualHostName);
        if (virtualHost == null) {
            return null;
        }
        Binding binding = virtualHost.getMemoryDataCenter().getBinding(exchangeName, queueName);
        if (binding != null) {
            return binding;
        }
        exchangeName = virtualHost.getName(exchangeName);
        queueName = virtualHost.getName(queueName);
        return virtualHost.getMemoryDataCenter().getBinding(exchangeName, queueName);
    }

    /**
     * 查找队列绑定的所有消息
     * @param queueName
     * @param virtualHostName
     * @return
     */
    public Map<String, Object> selectMessages(String queueName, String virtualHostName) {
        VirtualHost virtualHost = GlobalVariable.brokerServer.getVirtualHost(virtualHostName);
        HashMap<String, Object> map = new HashMap<>();
        map.put("list", new ArrayList<>());
        map.put("count", 0);

        if (virtualHost == null) {
            return map;
        }

        List<Message> messages = virtualHost.getMemoryDataCenter().getMessages(queueName);
        if (messages.size() != 0) {
            return map;
        }

        queueName = virtualHost.getName(queueName);
        messages = virtualHost.getMemoryDataCenter().getMessages(queueName);
        map.put("list", messages);
        map.put("count", messages.size());
        return map;
    }
}
